package pf

import (
	. "chess_platform/internal/common"
	"chess_platform/models/partner"
	"chess_platform/models/pc"
	"chess_platform/modules"
	"fmt"
	"github.com/astaxie/beego/orm"
	"time"
)

//[h5]订单
type OrderController struct {
	GrantController
}

func (b *OrderController) URLMapping() {
	b.Mapping("PayType", b.PayType)
	b.Mapping("IPayCreateOrder", b.IPayCreateOrder)
	b.Mapping("IPayAgentNumCO", b.IPayAgentNumCO)

	b.Mapping("BuyCard", b.BuyCard)
	b.Mapping("BuyAgentNum", b.BuyAgentNum)
	b.Mapping("CalBuyAgentNumPrice", b.CalBuyAgentNumPrice)
	b.Mapping("QueryOrder", b.QueryOrder)
}

// @Title 获取支付方式
// @Description 获取支付方式
// @Success 0 {string} 返回支付方式的id,1-爱贝,2-贝付宝
// @router /pay-type [post]
func (b *OrderController) PayType() {
	payType := modules.GetPayTypeByPlatform(PlatformClient)
	if payType == 0 {
		LogPF.Error("获取支付方式失败,用默认的支付方式返回给前端")
		b.Res.Data = PayTypeIPay
	} else {
		b.Res.Data = payType
	}
	b.ResponseSuccess()
}

// @Title h5助手里预支付(爱贝,代理购买钻石)
// @Description h5助手里预支付(爱贝,代理购买钻石))
// @Param   id             body    int true      "购买钻石数量对应的id"
// @Param   pay_type       body    int true      "支付类型,2-微信支付,3-支付宝支付"
// @Param   url_r          body    int true      "支付成功回调url"
// @Param   url_h          body    int true      "支付取消回调url"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /ipay-create-order [post]
func (b *OrderController) IPayCreateOrder() {
	type Params struct {
		Id      int64  `json:"id" valid:"Required"`
		PayType int64  `json:"pay_type" valid:"Range(2,3)"`
		UrlR    string `json:"url_r" valid:"Required"`
		UrlH    string `json:"url_h" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	//找出买多少张钻石，多少钱
	card, err := partner.CardById(p.Id, RulePartnerCardPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if card == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrCardNoExist
		b.Response()
		return
	}
	order := map[string]interface{}{
		"uid":        b.Uid, //代理id
		"order_type": OrderDiamond,
		"pay_type":   p.PayType,
		"amount":     card.Amount,
		"card_num":   card.Num,     //赠送的钻石与购买的暂时没有区别
		"give_num":   card.GiveNum, //搞活动系统赠送的钻石
		"status":     OrderNotPay,
		"order_time": time.Now().Unix(),
	}
	orderId, err := partner.PreOrderPay(order)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}

	notifyUrl := BasePayCallBack + "/v1/pf/ipay-callback"
	orderIdStr := fmt.Sprintf("%v%v", PfIPayPre, orderId)
	price := float32(card.Amount) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
	transId, err := H5IPay.CreateIpayOrder(1, "", orderIdStr, price, "xiashen", "", notifyUrl)
	if err != nil {
		LogPF.Error(b.SystemError(err.Error()))
		return
	}
	updateData := map[string]interface{}{
		"transaction_id": transId,
	}
	_, err = partner.UpdateOrder(updateData, orderId)
	if err != nil {
		LogPF.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
	}
	payUrl, err := H5IPay.GetHtml5PayUrl(transId, p.UrlR, p.UrlH, IPayPayType(p.PayType))
	if err != nil {
		LogPF.Error(b.SystemError(err.Error()))
		return
	}
	b.Res.Data = payUrl
	b.ResponseSuccess()
}

// @Title h5助手里预支付(爱贝,推广员购买代理名额)
// @Description h5助手里预支付(爱贝,推广员购买代理名额)
// @Param   agent_num      body    int true      "购买代理名额数量"
// @Param   pay_type       body    int true      "支付类型,2-微信支付,3-支付宝支付"
// @Param   url_r          body    int true      "支付成功回调url"
// @Param   url_h          body    int true      "支付取消回调url"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /ipay-agent-num-co [post]
func (b *OrderController) IPayAgentNumCO() {
	type Params struct {
		AgentNum int64  `json:"agent_num"`
		PayType  int64  `json:"pay_type" valid:"Range(2,3)"`
		UrlR     string `json:"url_r" valid:"Required"`
		UrlH     string `json:"url_h" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Min(p.AgentNum, 1, "agent_num").Message("请输入至少一个代理名额")
	if !b.ValidParams(&p) {
		return
	}
	//获取一个代理名额为多少钱
	r, err := partner.RuleByType(RuleAgentNumPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
	}
	if r.Id == 0 {
		LogPF.Error(b.SystemError("购买代理名额单价未设置,请检查!"))
		return
	}
	totalPrice := r.Amount * p.AgentNum

	order := map[string]interface{}{
		"uid":        b.Uid, //代理id
		"order_type": OrderAgentNum,
		"pay_type":   p.PayType,
		"amount":     totalPrice,
		"card_num":   p.AgentNum,
		"give_num":   0,
		"status":     OrderNotPay,
		"order_time": time.Now().Unix(),
	}
	orderId, err := partner.PreOrderPay(order)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}

	notifyUrl := BasePayCallBack + "/v1/pf/ipay-callback"
	orderIdStr := fmt.Sprintf("%v%v", PfIPayPre, orderId)
	price := float32(totalPrice) / 100 //我们数据库存在的整型,单位是分,所以要除以100转为元
	transId, err := H5IPay.CreateIpayOrder(1, "", orderIdStr, price, "xiashen", "", notifyUrl)
	if err != nil {
		LogPF.Error(b.SystemError(err.Error()))
		return
	}
	updateData := map[string]interface{}{
		"transaction_id": transId,
	}
	_, err = partner.UpdateOrder(updateData, orderId)
	if err != nil {
		LogPF.Error(fmt.Sprintf("写入爱贝的订单号失败:%v", err.Error()))
	}
	payUrl, err := H5IPay.GetHtml5PayUrl(transId, p.UrlR, p.UrlH, IPayPayType(p.PayType))
	if err != nil {
		LogPF.Error(b.SystemError(err.Error()))
		return
	}
	b.Res.Data = payUrl
	b.ResponseSuccess()
}

// @Title 进货钻石(余额支付)
// @Description 进货钻石(余额支付)
// @Param   id         body    int true      "购买钻石数量对应的id"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /buy-card [post]
func (b *OrderController) BuyCard() {
	type Params struct {
		Id int64 `json:"id" valid:"Required"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	if !b.ValidParams(&p) {
		return
	}

	//找出买多少张钻石，多少钱
	card, err := partner.CardById(p.Id, RulePartnerCardPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if card == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrCardNoExist
		b.Response()
		return
	}

	o := orm.NewOrm()
	o.Using(DBChessPartner)
	o.Begin()
	defer o.Rollback()

	//step 1: 判断余额是否足够支付
	cc, err := partner.CardCashById(b.Uid, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		o.Rollback()
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogPF.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TablePfCardCash))
		b.Response()
		return
	}
	if cc.Amount < card.Amount {
		o.Rollback()
		b.Res.Code = ErrCashNotEnough
		b.Res.Msg = MsgErrCashNotEnough
		b.Response()
		return
	}

	//step 2: 减少代理的余额,代理加上钻石
	cn, err := partner.UpdateCardCash(card.Num+card.GiveNum, -card.Amount, b.Uid, true, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cn == 0 {
		o.Rollback()
		b.ResponseFail("购买钻石失败")
		return
	}
	//step 3: 减少代理的余额记录
	cr := map[string]interface{}{
		"agent_id":    b.Uid,
		"type":        PfCashBalanceBuy,
		"card_num":    card.Num + card.GiveNum, //暂时不区别系统赠送的卡或购买的卡
		"amount":      -card.Amount,
		"month":       CurrentYearMonth(),
		"create_time": time.Now().Unix(),
	}
	_, err = partner.NewCashRecord(cr, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}

	//step 4:钻石记录加上,余额买卡
	handleCR := map[string]interface{}{
		"agent_id":    b.Uid,
		"card_num":    card.Num,
		"amount":      -card.Amount,
		"type":        BuyRoomCard,
		"pay_type":    BalancePay,
		"create_time": time.Now().Unix(),
	}
	_, err = partner.NewCardRecord(handleCR, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	//step 4:如果系统赠送的不为零,则要加上记录
	if card.GiveNum > 0 {
		handleSysGiveCR := map[string]interface{}{
			"agent_id":    b.Uid,
			"card_num":    card.GiveNum,
			"amount":      0, //这是系统赠送的，没有花钱
			"type":        SystemGiveRoomCard,
			"pay_type":    BalancePay,
			"create_time": time.Now().Unix(),
		}
		_, err = partner.NewCardRecord(handleSysGiveCR, o)
		if err != nil {
			o.Rollback()
			LogPF.Error(b.DatabaseError(err.Error()))
			return
		}
	}
	//发放提成
	err = modules.BonusPfAgent(b.Uid, card.Num, card.Amount, o)
	if err != nil {
		o.Rollback()
		eventLog := map[string]interface{}{
			"module":     ModuleCard,
			"event_type": EventDelivery,
			"user_type":  Agent,
			"uid":        b.Uid,
			"msg":        fmt.Sprintf("代理(ID:%v)余额买卡发放提成给代理失败:%v,请联系开发人员", b.Uid, err),
		}
		go NewEventLog(eventLog)
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()

	//直接把钻石充到合伙人的游戏ID帐号里
	err = modules.PfTopUp2GameId(b.Uid, card.Num+card.GiveNum)
	if err != nil {
		msg := fmt.Sprintf("代理:%v直接充值到自己的游戏ID失败:%v,请联系开发人员", b.Uid, err)
		eventLog := map[string]interface{}{
			"module":     ModuleCard,
			"event_type": EventDelivery,
			"user_type":  Agent,
			"uid":        b.Uid,
			"msg":        msg,
		}
		go NewEventLog(eventLog)
		LogPF.Error(msg)
	}

	//上面所有的操作都成功了才需求减少系统帐号的钻石,只要其中一步失败了，上面的所有操作都会回滚
	err = pc.DoSystemDiamond(SysPfBuyUid, -card.Num, b.Uid, SysOpBuy, -1, Agent)
	if err != nil {
		LogPF.Error(fmt.Sprintf("从Pf端系统购买帐号:%v扣钻石数:%v到代理(ID:%v)失败,操作类型为:%v,失败日志:%v",
			SysPfBuyUid, card.Num, b.Uid, SysOpBuy, err))
	}
	if card.GiveNum > 0 {
		err = pc.DoSystemDiamond(SysPfGiveUid, -card.GiveNum, b.Uid, SysOpBuyGive, -1, Agent)
		if err != nil {
			LogPF.Error(fmt.Sprintf("从Pf端系统赠送帐号:%v扣钻石数:%v到代理(ID:%v)失败,操作类型为:%v,失败日志:%v",
				SysPfGiveUid, card.GiveNum, b.Uid, SysOpBuyGive, err))
		}
	}
	b.ResponseSuccess()
}

// @Title 计算购买代理名额支付价格(一级代理才有权限)
// @Description 计算购买代理名额支付价格(一级代理才有权限)
// @Param   agent_num         body    int true      "购买代理名额数量"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /cal-buy-agent-num-price [post]
func (b *OrderController) CalBuyAgentNumPrice() {
	type Params struct {
		AgentNum int64 `json:"agent_num"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Min(p.AgentNum, 1, "agent_num").Message("请输入至少一个代理名额")
	if !b.VerifyParamsError() {
		return
	}
	//获取一个代理名额为多少钱
	r, err := partner.RuleByType(RuleAgentNumPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
	}
	if r.Id == 0 {
		LogPF.Error(b.SystemError("购买代理名额单价未设置,请检查!"))
		return
	}
	b.Res.Data = r.Amount * p.AgentNum
	b.ResponseSuccess()
}

// @Title 购买代理名额(余额支付)
// @Description 购买代理名额(余额支付)
// @Param   agent_num         body    int true      "购买代理名额数量"
// @Success 0 {string} 状态码
// @Failure 400
// @Failure 404
// @router /buy-agent-num [post]
func (b *OrderController) BuyAgentNum() {
	type Params struct {
		AgentNum int64 `json:"agent_num"`
	}
	var p Params
	if !b.DecodeParams(&p) {
		return
	}
	b.Valid.Min(p.AgentNum, 1, "agent_num").Message("请输入至少一个代理名额")
	if !b.VerifyParamsError() {
		return
	}
	//获取一个代理名额为多少钱
	r, err := partner.RuleByType(RuleAgentNumPrice)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))
	}
	if r.Id == 0 {
		LogPF.Error(b.SystemError("购买代理名额单价未设置,请检查!"))
		return
	}
	price := r.Amount * p.AgentNum

	o := orm.NewOrm()
	o.Using(DBChessCenter)
	o.Begin()
	defer o.Rollback()

	//step 1: 判断余额是否足够支付
	cc, err := partner.CardCashById(b.Uid, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cc.Uid == 0 {
		o.Rollback()
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrSystem
		LogPF.Error(fmt.Sprintf("代理:%d在表%v没有记录", b.Uid, TableH5CardCash))
		b.Response()
		return
	}
	if cc.Amount < price {
		o.Rollback()
		b.Res.Code = ErrCashNotEnough
		b.Res.Msg = MsgErrCashNotEnough
		b.Response()
		return
	}

	//step 2: 减少代理的余额
	cn, err := partner.UpdateCardCash(0, -price, b.Uid, false, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	if cn == 0 {
		o.Rollback()
		b.ResponseFail("购买名额失败")
		return
	}
	//代理加上代理名额
	_, err = partner.UpdateUserAgentNum(p.AgentNum, b.Uid, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}

	//step 3: 减少代理的余额记录
	cr := map[string]interface{}{
		"agent_id":    b.Uid,
		"type":        PfCashBalanceBuyAgentNum,
		"card_num":    0, //暂时不区别系统赠送的卡或购买的卡
		"amount":      -price,
		"month":       CurrentYearMonth(),
		"create_time": time.Now().Unix(),
	}
	_, err = partner.NewCashRecord(cr, o)
	if err != nil {
		o.Rollback()
		LogPF.Error(b.DatabaseError(err.Error()))
		return
	}
	o.Commit()
	b.ResponseSuccess()
}

// @Title 查询订单支付情况
// @Description 查询订单支付情况
// @Param   order_id         body    int true      "订单id"
// @Success 0 {string} 订单状态
// @Failure 400
// @Failure 404
// @router /query-order [post]
func (b *OrderController) QueryOrder() {
	type Params struct {
		OrderId int64 `json:"order_id"`
	}
	var p Params
	err := b.Unmarshal(&p)
	if err != nil {
		b.DecodeParamsError(err)
		return
	}
	order, err := partner.OrderById(p.OrderId)
	if err != nil {
		LogPF.Error(b.DatabaseError(err.Error()))

		return
	}
	if order == nil {
		b.Res.Code = ErrNotFound
		b.Res.Msg = MsgErrOrderNoExist
		b.Response()
		return
	}
	data := map[string]interface{}{
		"order_status": order.Status,
	}
	b.Res.Data = data
	b.ResponseSuccess()
}
